<html>
  <head>
    <meta charset='utf-8' />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>pg_tileserv: {{.ID}}</title>
    <script src="https://unpkg.com/maplibre-gl@2.1.9/dist/maplibre-gl.js"></script>
    <link href="https://unpkg.com/maplibre-gl@2.1.9/dist/maplibre-gl.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <style type="text/css">
      body {margin:0;padding:0;font-family:sans-serif;}
      #map {position:absolute;top:0;bottom:0;left:0;right:0;}
      #meta {z-index:2;color:black;background:rgba(255,255,255,0.6);position:absolute;top:10;left:20;padding:10 20;margin:0;width:min-content;}
      #meta h1 {margin:0;}
    </style>
  </head>
<body>

  <div id="meta">
    <h1>{{ .ID }}</h1>
    {{ if .Description }}
    <p>{{ .Description }}</p>
    {{ end }}
    <div id="arguments"></div>
  </div>

  <div id="map"></div>

  <script>

    // This string token utility makes the URL mucking
    // below a lot less ugly, takes 'this {0} that' and
    // replaces the numbered token with appropriate argument.
    if (!String.prototype.format) {
      String.prototype.format = function() {
        var args = arguments;
        return this.replace(/{(\d+)}/g, function(match, number) {
          return typeof args[number] != 'undefined'
            ? args[number]
            : match
          ;
        });
      };
    }

    var map;
    var mapcolor = "blue";

    $.getJSON("{{ .ID }}.json", function(layer) {
      // A little info for explorers
      console.log("{{ .ID }}.json");
      console.log(layer);

      layer["arguments"].forEach(function (item, i) {
        var nm = item["name"];
        var inm = "input-" + nm;
        var d = item["default"] || "";
        var lbl = "<label for='{0}'>{1}</label>".format(inm, nm);
        var inp = "<input id='{0}' value='{1}' size='10'>".format(inm, d);
        $("#arguments").append("<p>{0} {1}</p>".format(lbl, inp));
      });

      $("#arguments").append("<p><button id='refreshbutton'>Update</button></p>");
      $("#refreshbutton").on("click", function(e) {
        var args = {};
        layer["arguments"].forEach(function (item, i) {
          var nm = item["name"];
          var inm = "#input-" + nm;
          args[nm] = $(inm).val();
        });
        var argstr = jQuery.param(args);
        var tileurl = layer["tileurl"] + "?" + argstr;
        console.log("Tile URL = " + tileurl);
        removeFilteredLayers(layer.id);
        addFilteredLayers(layer.id, tileurl);
      });

      var mapConfig = {
        'container': 'map',
        // use 'bounds' or 'center/zoom' but not both at once
        // 'center': layer['center'],
        // 'zoom': layer['minzoom'],
        'bounds': layer['bounds'],
        'hash': true,
        'style': {
          'version': 8,
          'sources': {
            'carto-dark': {
              'type': 'raster',
              'tiles': [
                "https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png",
                "https://b.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png",
                "https://c.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png",
                "https://d.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png"
              ]
            },
            'carto-light': {
              'type': 'raster',
              'tiles': [
                "https://a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png",
                "https://b.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png",
                "https://c.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png",
                "https://d.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png"
              ]
            },
            'wikimedia': {
              'type': 'raster',
              'tiles': [
                "https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png"
              ]
            }
          },
          'layers': [{
            // 'id': 'carto-dark-layer',
            // 'source': 'carto-dark',
            'id': 'carto-light-layer',
            'source': 'carto-light',
            // 'id': 'wikimedia-layer',
            // 'source': 'wikimedia',
            'type': 'raster',
            'minzoom': 0,
            'maxzoom': 22
          }]
        }
      };

      var paints = {
        "circle":{
          "circle-color": mapcolor,
          "circle-radius": 3
        },
        "line":{
          "line-width": 1.5,
          "line-color": mapcolor
        },
        "fill":{
          "fill-color": mapcolor,
          "fill-opacity": 0.1,
          "fill-outline-color": mapcolor
        }
      };

      function layerSource(tileurl) {
        return {
          "type": "vector",
          "tiles": [tileurl],
          "minzoom": layer["minzoom"],
          "maxzoom": layer["maxzoom"]
        }
      };

      function layerId(id, gtype, paint) {
        return id+"."+gtype+"."+paint;
      }

      function layerConfig(id, gtype, paint) {
        return {
          "id": layerId(id, gtype, paint),
          "source": id,
          // Function-layers implementors will decide on an arbitrary
          // layer name inside the tile. Most often, they will keep
          // the name "default" as it is ST_AsMVT() default value
          // for this parameter.
          "source-layer": "default",
          "type": paint,
          "paint": paints[paint],
          "filter": ["match", ["geometry-type"], [gtype, "Multi"+gtype], true, false]
        }
      };

      // Convert feature properties into html
      function featureHtml(f) {
        var p = f.properties;
        var h = "<p>";
        for (var k in p) {
          h += "<b>" + k + ":</b> " + p[k] + "<br/>"
        }
        h += "</p>";
        return h
      }

      function addLayerBehavior(id) {
        // When a click event occurs on a feature in the states layer, open a popup at the
        // location of the click, with description HTML from its properties.
        map.on('click', id, function(e) {
          new maplibregl.Popup()
          .setLngLat(e.lngLat)
          .setHTML(featureHtml(e.features[0]))
          .addTo(map);
        });

        // // Change the cursor to a pointer when the mouse is over the states layer.
        map.on('mouseenter', id, function() {
          map.getCanvas().style.cursor = 'pointer';
        });

        // // Change it back to a pointer when it leaves.
        map.on('mouseleave', id, function() {
          map.getCanvas().style.cursor = '';
        });
      }

      function addFilteredLayers(id, url) {
        map.addSource(id, layerSource(url));
        // Render as point if point
        map.addLayer(layerConfig(id, "Point", "circle"));
        addLayerBehavior(layerId(id, "Point", "circle"));
        // Render as line if line
        map.addLayer(layerConfig(id, "LineString", "line"));
        addLayerBehavior(layerId(id, "LineString", "line"));
        // Render as area (fill) and line (outline) if polygon
        map.addLayer(layerConfig(id, "Polygon", "fill"));
        addLayerBehavior(layerId(id, "Polygon", "fill"));
        map.addLayer(layerConfig(id, "Polygon", "line"));
      }

      function removeFilteredLayers(id) {
        map.removeLayer(layerId(id, "Point", "circle"));
        map.removeLayer(layerId(id, "LineString", "line"));
        map.removeLayer(layerId(id, "Polygon", "fill"));
        map.removeLayer(layerId(id, "Polygon", "line"));
        map.removeSource(id);
      }

      map = new maplibregl.Map(mapConfig);
      map.addControl(new maplibregl.NavigationControl());

      map.on("load", function() {

        addFilteredLayers(layer["id"], layer["tileurl"]);




      });

    });

  </script>

</body>
</html>
